package com.axend.vetwavve.helper

import android.graphics.Bitmap
import android.util.Log
import com.axend.lib_base.ext.roundToOne
import com.axend.lib_base.utils.DateUtils
import com.axend.lib_base.utils.FileOutputUtil
import org.opencv.android.OpenCVLoader
import org.opencv.android.Utils
import org.opencv.core.*
import org.opencv.imgcodecs.Imgcodecs
import org.opencv.imgproc.Imgproc
import kotlin.math.abs

class FaceMotionDetectHelper(rect: Rect? = null) {

    init {
        if (OpenCVLoader.initDebug()) {
            Log.i("MotionDetectHelper", "OpenCV loaded successfully")
        } else {
            Log.e("MotionDetectHelper", "OpenCV initialization failed!")
        }
    }

    private var previousFrame: Mat? = null
    private var currentFrame: Mat? = null
    private var targetRect: Rect = rect ?: Rect()
    private var frameCount = 0
    private var savePosition = 0
    private var kernel: Mat? = null

    private var n = 0
    private var mean = 0.0
    private var state = 0
    private var changeTime: Long = 0
    private var keep = 0
    private var intrudeTime: Long = Long.MIN_VALUE
    private val meanHistory = ArrayList<Double>()
    private var resolution: IntArray? = null
    private val cameraObj = ArrayList<Any>()
    private var cacheTime = 5
    private var cameraBoxRate = 100 // 1s 考虑到误识别框一直存在，最多允许 相机数2*识别帧数5*帧最多允许10个目标
    private var heartTime: Long = 0
    private var dataSize = 5
    private var cachedMeanDiff: DoubleArray? = null

    /**
     * Process Infrared Thermal Imaging Target Motion
     */
    fun processThermalImagingTargetMotion(p0: Bitmap, callback: FaceMotionDetectCallback): Bitmap {
        currentFrame = currentFrame ?: Mat()

        frameCount++
        if (frameCount % 3 == 0) {
            Utils.bitmapToMat(p0, currentFrame!!)

            val currentRoi = Mat(currentFrame!!, targetRect) // Current frame ROI
            val currentRoiGray = Mat() // Grayscale image of the current frame ROI
            Imgproc.cvtColor(currentRoi, currentRoiGray, Imgproc.COLOR_RGBA2GRAY)

            val meanVal = Core.mean(currentRoiGray) // 灰度图像
            val meanValue = meanVal.`val`[0].roundToOne()
            updateState(meanValue, callback)

            currentRoiGray.release()
            return p0
        } else {
            currentFrame?.release()
            Utils.bitmapToMat(p0, currentFrame!!)
            return p0
        }
    }

    fun release() {
        currentFrame?.release()
    }

    // 更新状态方法
    private fun updateState(v: Double, callback: FaceMotionDetectCallback) {
        n++
        val delta = v - mean
        val newMean = (mean + delta * (1.0 / n)).roundToOne()

        meanHistory.add(newMean)
        if (meanHistory.size > dataSize) {
            meanHistory.removeAt(0)
        }

        // 更新缓存的meanDiff
        if (meanHistory.size > 1) {
            if (cachedMeanDiff == null || cachedMeanDiff!!.size != meanHistory.size - 1) {
                cachedMeanDiff = DoubleArray(meanHistory.size - 1)
            }
            for (i in 1 until meanHistory.size) {
                cachedMeanDiff!![i - 1] = meanHistory[i] - meanHistory[i - 1]
            }
        } else {
            cachedMeanDiff = DoubleArray(0)
        }

        val meanDiff = cachedMeanDiff!!

        var rateAdd = 0.0
        var rateSub = 0.0
        for (diff in meanDiff) {
            if (diff > 0) {
                rateAdd += diff
            } else {
                rateSub += abs(diff)
            }
        }

        if (rateAdd > (rateAdd + rateSub) * 0.72) { // 上升占比超过百分之70
            if (state == 1) {
                keep++
            } else {
                keep = 1
                state = 1
            }
            mean = v
            n = 1
        } else if (rateSub > (rateAdd + rateSub) * 0.72) { // 下降占比超过百分之70
            if (state == -1) {
                keep++
            } else {
                keep = 1
                state = -1
            }
            if (keep > 6) {
                intrudeTime = System.nanoTime()
                // 脸部移动报警
                callback.onMotionDetected("$keep ,$newMean , $state")
            }
            mean = v
            n = 1
        } else { // 上升或下降相对均衡
            state = 0
        }

        keep = minOf(keep, 100000)
        n = minOf(n, 100000)
        callback.onLogOut("$keep ,$newMean , $state")
        //调试文件输出
        val title = "Time\tnewMean\tstate\tkepp"
        val fileName = "faceMotionData"
        FileOutputUtil.writeHeadToFile(fileName, title)
        val content = "\r\n${DateUtils.getCurrentTime()}\t$newMean\t${state}\t$keep"
        FileOutputUtil.writeTextToFile(fileName, content)
    }
}
